package com.wangsan.study.web;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.util.UriComponentsBuilder;

import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.wangsan.study.security.AuthMapping;
import com.wangsan.study.security.ResourceAuth;
import com.wangsan.study.security.ResourceAuthItem;
import com.wangsan.study.web.security.AnnotationResourceAuthResolver;

import springfox.documentation.annotations.ApiIgnore;
import springfox.documentation.service.ApiDescription;
import springfox.documentation.service.ApiListing;
import springfox.documentation.service.Documentation;
import springfox.documentation.spring.web.DocumentationCache;
import springfox.documentation.spring.web.plugins.Docket;

@Controller
public class HelloController {

    @Autowired
    private List<HandlerMapping> handlerMappingList;
    @Autowired
    private DocumentationCache documentationCache;
    @Autowired
    private AnnotationResourceAuthResolver resourceAuthResolver;

    @ApiIgnore
    @AuthMapping(value = "/hello", method = RequestMethod.GET, authName = "test wangsan")
    @ResponseBody
    public String hello() {
        return "Hello World";
    }

    @ApiIgnore
    @ResourceAuth("test by wangsan")
    @RequestMapping(value = "/hello2", method = RequestMethod.GET)
    @ResponseBody
    public String hello2() {
        UriComponentsBuilder uriComponentsBuilder = MvcUriComponentsBuilder.fromController(UserEntityController.class);
        System.err.println(uriComponentsBuilder);
        return "Hello2 World";
    }

    @GetMapping(value = {"/index", "/"})
    public String index(Model model) {
        model.addAttribute("name", "wangsan");
        return "index";
    }

    @RequestMapping(value = "/allAuth", method = RequestMethod.GET)
    @ResponseBody
    public List<ResourceAuthItem> allAuth(Model model) {
        List<ResourceAuthItem> resourceAuthItemList = resourceAuthResolver.getResourceAuthItemList();
        return resourceAuthItemList;
    }

    @RequestMapping(value = "/allMvcMap", method = RequestMethod.GET)
    @ResponseBody
    public List<String> allMvcMap(Model model) {
        List<String> urlList = Lists.newArrayList();
        handlerMappingList.forEach(handlerMapping -> {
            if (handlerMapping.getClass().isAssignableFrom(SimpleUrlHandlerMapping.class)) {
                SimpleUrlHandlerMapping simpleUrlHandlerMapping = (SimpleUrlHandlerMapping) handlerMapping;
                urlList.addAll(simpleUrlHandlerMapping.getUrlMap().keySet());
            } else if (handlerMapping.getClass().isAssignableFrom(RequestMappingHandlerMapping.class)) {
                RequestMappingHandlerMapping requestMappingHandlerMapping =
                        (RequestMappingHandlerMapping) handlerMapping;
                Map<RequestMappingInfo, HandlerMethod> handlerMethods =
                        requestMappingHandlerMapping.getHandlerMethods();
                urlList.addAll(
                        handlerMethods.keySet().stream().map(info -> info.toString()).collect(Collectors.toList()));
            }
        });

        return urlList;
    }

    @RequestMapping(value = "/allSwaggerApi", method = RequestMethod.GET)
    @ResponseBody
    public List<ResourceAuthItem> allSwaggerApi(Model model) {
        List<ResourceAuthItem> resourceAuthItemList = Lists.newArrayList();

        Documentation documentation = documentationCache.documentationByGroup(Docket.DEFAULT_GROUP_NAME);
        Multimap<String, ApiListing> apiListings = documentation.getApiListings();
        apiListings.asMap().forEach((key, apiListingList) -> {
            for (ApiListing apiListing : apiListingList) {
                String resourceType = tagToString(apiListing.getTags());

                for (ApiDescription apiDescription : apiListing.getApis()) {
                    String resourceAction = null;
                    String path = null;

                    path = apiDescription.getPath();
                    Set<String> tags = apiDescription.getOperations().get(0).getTags();
                    resourceAction = tagToString(tags);

                    ResourceAuthItem item = new ResourceAuthItem();
                    item.setPath(path);
                    item.setGroup(resourceType);
                    item.setName(resourceAction);

                    resourceAuthItemList.add(item);
                }
            }
        });

        return resourceAuthItemList;
    }

    public String tagToString(Set<String> tagSet) {
        if (!CollectionUtils.isEmpty(tagSet)) {
            return tagSet.iterator().next();
        }
        return null;
    }

}